package Finance::NSCC::Insurance::File::COM;

use Moose;
extends 'Finance::NSCC::Insurance::File';
use Finance::NSCC::Insurance::Utils qw/trim/;

our $VERSION = '0.00100';

our $RHEADER = qr/^C20(.{4})COM.{4}(.{8}).{6}0001.{8}(.{12})(.)(.{10}).{237}$/;
our $R21   = qr/^C21(.{4})(.{4})(.{10})(.{10})(.{8})(.{8}).{253}$/;
our $R2201 = qr/^C2201(.{20})(...)(.{20})(..)(.{9})(.{30})(.{8})(.{8})(.{8})(.{8})(.)(.{16})(.)(.{16})(.)(.{16})(.{3})(..)(..)(.)(...)(..)...{16}(.{30})(.{3}).{64}$/;
our $R2202 = qr/^C2202(.{20})(.{30})(.{8})(.{10})(.)(.{16})(.{30})(.{30})(.{16})(.)(.{10})(..).{121}$/;
our $R2203 = qr/^C2203(.{20})(.{9})(.{5})(.{5})(.{16})(..)(.{10})(.{16})(.)(.)(.{9}).{201}$/;
our $R2204 = qr/^C2204(.{20})((.{35})(.{25})(.{25})(.{10})(.{10}))(..)(.{8})(.{20})(..)(...)(.).{134}$/;
our $R2205 = qr/^C2205(.{20})(.{20})(..)(..)((.{35})(.{25})(.{25})(.{10})(.{10}))(.{30})(.)(.{10}).{5}(.{16})(.)(.{10}).{73}$/;

sub _build_records {
  my $self = shift;
  my $io = $self->_file_handle;

  my $record_count = 1; #header is already processed
  my @records;
  my $line = $io->getline or $self->_error("Premature end before C21 record.");
  $record_count++;
  #CONTRA record
  if ( $line !~ /$R21/ ) {
    $self->_error("'$line' where C21 record expected.");
  }
  defined($line = $io->getline) or $self->_error("Premature end on C21 record.");
  $record_count++;

  #contracts loop
  while ( my (@m01) = map{ trim $_} ($line =~ /$R2201/)) {
    my $contract = {
                    nscc_num         => $self->nscc_num,
                    prod_type_code   => $m01[20],
                    cusip            => $m01[4],
                    contract_num     => $m01[5],
                   };
    push(@records, $contract);

    if ($m01[3]) {
      $contract->{erc_id}   = $m01[2];
      $contract->{erc_id_q} = $m01[3];
    }

    $contract->{owner_state}      = $m01[17] if $m01[17];
    $contract->{app_signed_state} = $m01[18] if $m01[18];
    $contract->{trail_freq_i    } = $m01[21] if $m01[21];
    $contract->{group_num}        = $m01[25] if $m01[25];

    my $commission = {
                      nscc_control_num  => $m01[0],
                      prepaid_amt => ($m01[13] / 100) * ($m01[12] == 2 ? 1 : -1),
                      basis_amt   => ($m01[15] / 100) * ($m01[14] == 2 ? 1 : -1),
                      basis_reason_code => $m01[16],
                     };
    $contract->{commission} = $commission;

    $commission->{coverage_duration} = $m01[27] if $m01[26];
    $commission->{trans_effective_d} = $m01[6]  if $m01[6]; #XXX date
    $commission->{settle_d}          = $m01[7]  if $m01[7]; #XXX date
    $commission->{process_d}         = $m01[8]  if $m01[8]; #XXX date

    if ($commission->{trans_effective_d}) {
      $commission->{trans_effective_d} =~ s/(....)(..)(..)/$1-$2-$3/;
    }
    if ($commission->{settle_d}) {
      $commission->{settle_d} =~ s/(....)(..)(..)/$1-$2-$3/;
    }
    if ($commission->{process_d}) {
      $commission->{process_d} =~ s/(....)(..)(..)/$1-$2-$3/;
    }

    if ($m01[9]) {
      my $policy_effective_d = $m01[9];
      $policy_effective_d =~ s/(....)(..)(..)/$1-$2-$3/; #XXX date
      $contract->{dates} = [{date_v => $policy_effective_d, date_q => '092'}];
    }
    defined($line = $io->getline) && $record_count++;

    if ( my (@m02) = map{ trim $_} ($line =~ /$R2202/)) {
      $contract->{dist_acct_num} = $m02[1] if $m02[1];
      $contract->{valuation_d}   = $m02[2] if $m02[2];
      if ( $contract->{valuation_d} ) {
        $contract->{valuation_d} =~ s/(....)(..)(..)/$1-$2-$3/; #XXX date
      }
      if ($m02[3]) {
        $commission->{rate} = ($m02[3] / 10**9);
      }
      $contract->{comm_opt}        = $m02[6] if $m02[6];
      $commission->{dist_trans_id} = $m02[7] if $m02[7];
      if ($m02[9] ne "") {
        $commission->{total_premium_amt} = ($m02[8] / 100) * ($m02[9] == 2 ? 1 : -1);
      }
      $contract->{comm_ext} = $m02[10] if $m02[10];
      $commission->{premium_payment_mode} = $m02[11] if $m02[11];
      defined($line = $io->getline) && $record_count++;
    }

    while ( my (@m03) = map{ trim $_} ($line =~ /$R2203/)) {
      $record_count++;
      $commission->{underlying_assets} ||= [];
      my $fund = {
                  cusip            => $m03[1],
                  fund_id          => $m03[2],
                  sub_fund_id      => $m03[3],
                  comm_basis_amt   => ($m03[4] / 100) * ($m03[9] == 2 ? 1 : -1),
                  comm_basis_amt_q => $m03[5],
                  calc_comm_amt    => ($m03[7] / 100) * ($m03[8] == 2 ? 1 : -1),
                 };
      $fund->{comm_rate} = ($m03[6] / 10**9) if($m03[6] * 1); #zerofill workaround
      $fund->{fund_cusip} = $m03[10] if $m03[10];
      push(@{$commission->{underlying_assets}}, $fund);
      defined($line = $io->getline) && $record_count++;
    }
    while ( my (@m04) = map{ trim $_} ($line =~ /$R2204/)) {
      $contract->{parties} ||= [];
      my $party = {
                   role     => $m04[7],
                   entity_i => $m04[12] eq 'X' ? 1 : 0,
                  };
      push(@{$contract->{parties}}, $party);

      if ($party->{entity_i}) {
        $party->{entity_name} = $m04[1];
      } else {
        $party->{last_name}   = $m04[2];
        $party->{first_name}  = $m04[3] if $m04[3];
        $party->{middle_name} = $m04[4] if $m04[4];
        $party->{prefix}      = $m04[5] if $m04[5];
        $party->{suffix}      = $m04[6] if $m04[6];
      }
      if ( $m04[8] ) {
        $party->{dob} = $m04[8];
        $party->{dob} =~ s/(....)(..)(..)/$1-$2-$3/; #XXX date
        $party->{dob_q} = $m04[11] if $m04[11];
      }
      if ($m04[10]) {
        $party->{tax_id}   = $m04[9];
        $party->{tax_id_q} = $m04[10];
      }
      defined($line = $io->getline) && $record_count++;
    }
    while ( my (@m05) = map{ trim $_} ($line =~ /$R2205/)) {
      $commission->{recipients} ||= [];
      my $recipient = {
                       role     => $m05[3],
                       tax_id   => $m05[1],
                       tax_id_q => $m05[2],
                       entity_i => $m05[11] eq 'X' ? 1 : 0,
                      };

      push(@{$commission->{recipients}}, $recipient);
      if ($recipient->{entity_i}) {
        $recipient->{entity_name} = $m05[4];
      } else {
        $recipient->{last_name}   = $m05[5];
        $recipient->{first_name}  = $m05[6] if $m05[6];
        $recipient->{middle_name} = $m05[7] if $m05[7];
        $recipient->{prefix}      = $m05[8] if $m05[8];
        $recipient->{suffix}      = $m05[9] if $m05[9];
      }
      $recipient->{brokers_id} = $m05[10] if $m05[10];
      $recipient->{national_producer_num} = $m05[12] if $m05[12];
      if ($m05[14]) {
        $recipient->{comm_amt} = ($m05[13] / 100) * ($m05[14] == 2 ? 1 : -1);
      }
      $recipient->{comm_pct} = ($m05[15] / 10**9) if $m05[15];
      defined($line = $io->getline) && $record_count++;
    }
  }
  my $target = $self->record_count;
  $self->_error("Record and target count mismatch ($record_count : $target)")
    unless $target == $record_count;
  $self->_clear_file_handle;      #close the filehandle
  return \@records;
}

1;
